﻿/*========================== 
 * @author 郑金泉
 * @desc 实体类
 * ========================= */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

using Obsidian.Config;
using Obsidian.Data.Sql;
using Obsidian.Data.Sql.SqlSrvClient;
using Obsidian.Data.Sql.OleDbClient;
using Obsidian.Data.Sql.MySqlClient;

namespace Obsidian.Edm
{
    public abstract class OModel : IModel
    {
        private Dictionary<string, IModelField> dictFieldByQueryAlias;
        private Dictionary<string, IModelField> dictFieldByAlias;

        public static bool ExistPk<T>(object val) where T : IModel, new()
        {
            T m = new T();
            IModelField pkField = m.PimaryKey;
            if (pkField == null)
                throw new Exception("未设置主键");
            IDbHandler dbh = m.CreateHandler();
            dbh.SetField(pkField);
            dbh.Where(pkField.Equals(val));
            DataReader dr = dbh.Select();
            bool exist = false;
            if (dr.Read())
                exist = true;
            dr.Close();
            return exist;
        }

        public static T GetByPk<T>(object val) where T : IModel, new()
        {
            T m = new T();
            if (m.GetByPrimaryKey(val))
                return m;
            else
                return default(T);
        }

        public static bool DeleteByPk<T>(object val) where T : IModel, new()
        {
            T m = new T();
            if(m.PimaryKey == null)
                throw new Exception("没有设置主键");
            IDbHandler dbh = m.CreateHandler();
            dbh.Where(m.PimaryKey.Equals(val));
            return dbh.Delete() > 0;
        }

        private string _dbAlias = null;
        public string DbAlias
        {
            get { return this._dbAlias; }
        }

        private string _dbTableName = null;
        /// <summary>
        /// 数据库表名
        /// </summary>
        public string DbTableName
        {
            get { return this._dbTableName; }
        }

        private DataBase _dataBase = null;
        /// <summary>
        /// 获得映射数据库信息
        /// </summary>
        /// <returns></returns>
        public DataBase GetDataBase()
        {
            if (this._dataBase == null)
            {
                if (String.IsNullOrEmpty(this._dbAlias))
                    throw new Exception("未设置映射数据库配置!");
                this._dataBase = DataBase.Get(this._dbAlias);
            }
            return this._dataBase;
        }

        private DbTable _dbTable = null;
        /// <summary>
        /// 获得映射数据库表
        /// </summary>
        /// <returns></returns>
        public DbTable GetDbTable()
        {
            if (this._dbTable == null)
            {
                if (String.IsNullOrEmpty(this._dbTableName))
                    throw new Exception("未设置映射数据库表配置!");
                DataBase db = this.GetDataBase();
                this._dbTable = db.GetTable(this._dbTableName);
            }
            return this._dbTable;
        }

        private IModelField[] _fields = null;
        /// <summary>
        /// 获得字段
        /// </summary>
        public IModelField[] Fields
        {
            get { return this._fields; }
        }

        private IModelField _pimaryKey = null;
        public IModelField PimaryKey
        {
            get
            {
                if (this._pimaryKey == null)
                {
                    foreach (IModelField field in this.Fields)
                    {
                        DbField f = field.GetDbField();
                        if (f != null && f.IsPrimaryKey)
                        {
                            this._pimaryKey = field;
                            break;
                        }
                    }
                }
                return this._pimaryKey;
            }
        }

        protected void InitModel(string dbAlias, string dbTableName, IModelField[] fields)
        {
            this._dbAlias = dbAlias;
            this._dbTableName = dbTableName;
            this._fields = fields;
        }

        protected void InitModel(IModelField[] fields)
        {
            this._fields = fields;
        }

        /// <summary>
        /// 根据字段查询别名获得字段
        /// </summary>
        /// <param name="queryAlias"></param>
        /// <returns></returns>
        public IModelField GetFieldByQueryAlias(string queryAlias)
        {
            if (dictFieldByQueryAlias == null)
            {
                dictFieldByQueryAlias = new Dictionary<string, IModelField>();
                foreach (IModelField field in this.Fields)
                {
                    DbField f = field.GetDbField();
                    if (f != null)
                        dictFieldByQueryAlias.Add(f.QueryAlias, field);
                }
            }
            if (dictFieldByQueryAlias.ContainsKey(queryAlias))
                return dictFieldByQueryAlias[queryAlias];
            else
                return null;
        }

        public IModelField GetFieldByAlias(string alias)
        {
            if (dictFieldByAlias == null)
            {
                dictFieldByAlias = new Dictionary<string, IModelField>();
                foreach (IModelField field in this.Fields)
                {
                    string falias = field.Alias;
                    if (!String.IsNullOrEmpty(falias))
                        dictFieldByAlias.Add(falias, field);
                }

            }
            if (dictFieldByAlias.ContainsKey(alias))
                return dictFieldByAlias[alias];
            else
                return null;
        }

        public IDbHandler CreateHandler()
        {
            switch (this.GetDataBase().Type)
            {
                case DataBaseType.SqlServer:
                    return new SqlSrvDbHandler(this);
                case DataBaseType.OleDb:
                    return new OleDbHandler(this);
                case DataBaseType.MySql:
                    return new MySqlDbHandler(this);
                default:
                    return null;
            }
        }

        public IModel SetTo(IModel targetModel)
        {
            foreach (IModelField field in this.Fields)
            {
                string alias = field.Alias;
                IModelField mf = targetModel.GetFieldByAlias(alias);
                if (mf != null)
                    mf.Set(field.OValue);
            }
            return this;
        }

        public IModel SetTo(IModel targetModel, string aliases)
        {
            if (String.IsNullOrEmpty(aliases))
                throw new Exception("参数fieldAliases不能为空");
            string[] arr = aliases.Split(',');
            foreach (string alias in arr)
            {
                IModelField mf = this.GetFieldByAlias(alias);
                if (mf == null)
                    throw new Exception(String.Format("别名为{0}的字段不存在", alias));
                IModelField mfTarget = targetModel.GetFieldByAlias(alias);
                if (mfTarget == null)
                    throw new Exception(String.Format("目标实体别名为{0}的字段不存在", alias));
                mfTarget.Set(mf.OValue);
            }
            return this;
        }

        #region

        public void ResetAssigned()
        {
            foreach (IModelField field in this.Fields)
            {
                if (field.Assigned)
                    field.Assigned = false;
            }
        }

        public bool GetByPrimaryKey(object pkValue)
        {
            if (pkValue == null)
                throw new Exception("主键值不能为空！");
            IDbHandler dbh = this.CreateHandler();
            dbh.SetFields(this.Fields)
                .Where(this.PimaryKey.Compare("=", pkValue));
            return dbh.SelectFirstTo(this);
        }

        public void Save()
        {
            IDbHandler dbh = this.CreateHandler();
            foreach (IModelField field in this.Fields)
            {
                DbField dbf = field.GetDbField();
                if (dbf != null && !dbf.IsAutoIncrement)
                {
                    if (field.IsNull)
                    {
                        dbh.SetField(field, DBNull.Value);
                    }
                    else
                    {
                        if (field.Type == FieldType.Enum || field.IsList)
                            dbh.SetField(field, field.ToString());
                        else
                            dbh.SetField(field, field.OValue);
                    }
                }
            }
            object val = dbh.Insert();
            IModelField f = this.PimaryKey;
            if (f != null && f.GetDbField().IsAutoIncrement)
                f.Set(val);
        }

        public bool Update()
        {
            IDbHandler dbh = this.CreateHandler();
            IModelField pk = this.PimaryKey;
            if (pk == null)
                throw new Exception("没有设置主键");
            if (pk.IsNull)
                throw new Exception("主键值不能为空！");
            foreach (IModelField field in this.Fields)
            {
                DbField dbf = field.GetDbField();
                if (dbf != null && !dbf.IsPrimaryKey && !dbf.IsAutoIncrement && field.Assigned)
                {
                    if (field.IsNull)
                    {
                        dbh.SetField(field, DBNull.Value);
                    }
                    else
                    {
                        if (field.Type == FieldType.Enum || field.IsList)
                        {
                            dbh.SetField(field, field.ToString());
                        }
                        else
                        {
                            dbh.SetField(field, field.OValue);
                        }
                    }
                }
            }
            dbh.Where(pk.Compare("=", pk.OValue));
            return dbh.Update() == 1;
        }

        public bool Delete()
        {
            IDbHandler dbh = this.CreateHandler();
            IModelField pk = this.PimaryKey;
            if (pk == null)
                throw new Exception("没有设置主键");
            if (pk.IsNull)
                throw new Exception("主键值不能为空！");
            dbh.Where(pk.Compare("=", pk.OValue));
            return dbh.Delete() == 1;
        }

        public bool Exists(params object[] pkValues)
        {
            IDbHandler dbh = this.CreateHandler();
            IModelField pk = this.PimaryKey;
            if (pk == null)
                throw new Exception("没有设置主键");
            dbh.SetField(pk);
            dbh.Where(pk.In(pkValues));
            DataReader dr = dbh.Select();
            Dictionary<object, object> dict = new Dictionary<object, object>(pkValues.Length);
            foreach(object o in pkValues)
                dict.Add(o, null);
            while (dr.Read())
            {
                object pkValue = dr.GetValue(pk);
                if (!dict.ContainsKey(pkValue))
                    return false;
            }
            dr.Close();
            return true;
        }

        #endregion

    }
}
